package com.xhs.main.shiro;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro的核心配置
 * @create 2020-10-24 18:46
 */
@Configuration
public class ShiroConfig {

  /**
   * 自定义realm;
   */
  @Bean
  public ShiroRealm shiroRealm() {
    return new ShiroRealm();
  }



  /** shiro核心类 */
  @Bean
  public SecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // 将自定义的Realm放进去
    securityManager.setRealm(shiroRealm());
    return securityManager;
  }


  /**
   * shiro核心过滤器
   * */
  @Bean
  public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    // 定义 shiroFactoryBean
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // 设置自定义的 securityManager
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    //没有登录认证的用户，访问的url
    shiroFilterFactoryBean.setLoginUrl("/yfb/login.html");
    // 设置成功之后要跳转的链接
//        shiroFilterFactoryBean.setSuccessUrl("/index");
    // 设置未授权界面，权限认证失败会访问该 URL
//        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

    // 配置拦截器
    // 配置拦截路径 LinkedHashMap 是有序的，进行顺序拦截器配置
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
  //anon放行
    filterChainDefinitionMap.put("/api/**", "anon");
    filterChainDefinitionMap.put("/css/**", "anon");
    filterChainDefinitionMap.put("/images/**", "anon");
    filterChainDefinitionMap.put("/js/**", "anon");
    filterChainDefinitionMap.put("/lib/**", "anon");
    // 登录 URL 放行
    filterChainDefinitionMap.put("/user/login", "anon");
    // 配置 logout 过滤器
    filterChainDefinitionMap.put("/user/logout", "logout");

    // 以“/user/admin” 开头的用户需要身份认证，authc 表示要进行身份认证
//        filterChainMap.put("/user/admin*", "authc");
    // “/user/student” 开头的用户需要角色认证，是“admin”才允许
//        filterChainMap.put("/user/student*/**", "roles[admin]");
    // “/user/teacher” 开头的用户需要权限认证，是“user:create”才允许
//        filterChainMap.put("/user/teacher*/**", "perms[\"user:create\"]");

    filterChainDefinitionMap.put("/**", "authc");
    // 设置 shiroFilterFactoryBean 的 FilterChainDefinitionMap
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
  }




  /**
   *  开启开启shiro aop注解支持，不开启的话权限验证就会失效
   */
  @Bean
  public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
    DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    advisorAutoProxyCreator.setProxyTargetClass(true);
    return advisorAutoProxyCreator;
  }

  /**
   * 配置支持注解授权的顾问
   */
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
  }


  //cookie对象;
  @Bean
  public SimpleCookie rememberMeCookie() {
    System.out.println("ShiroConfiguration.rememberMeCookie()");
    //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
    SimpleCookie simpleCookie = new SimpleCookie("rememberMe");

    //<!-- 记住我cookie生效时间30天 ,单位秒;-->
    simpleCookie.setMaxAge(259200);
    return simpleCookie;
  }

  //cookie管理对象;
  @Bean
  public CookieRememberMeManager cookieRememberMeManager() {
    System.out.println("ShiroConfiguration.rememberMeManager()");
    CookieRememberMeManager manager = new CookieRememberMeManager();
    manager.setCookie(rememberMeCookie());
    return manager;
  }
}
